package com.txzt.gaea.base.service.impl;

import com.txzt.base.core.RtnInfo;
import com.txzt.gaea.api.client.AdminUserRemoteService;
import com.txzt.gaea.base.dto.DataPermissionDTO;
import com.txzt.gaea.base.model.DataPermission;
import com.txzt.gaea.base.service.DataPermissionService;
import com.txzt.gaea.base.vo.DataPermissionVo;
import com.txzt.gaea.common.base.service.impl.BaseServiceImpl;
import com.txzt.gaea.common.core.base.context.AdminUserContext;
import com.txzt.gaea.common.enums.DataPermissionTypeEnum;
import com.txzt.gaea.common.enums.IsDeleteEnum;
import com.txzt.gaea.common.page.PageInfoBT;
import com.txzt.gaea.common.util.StringUtil;
import com.txzt.gaea.dto.UserSingleDetailQueryDTO;
import com.txzt.gaea.vo.AdminUserVO;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.beetl.sql.core.engine.PageQuery;
import org.beetl.sql.core.query.LambdaQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Log4j2
@Service
public class DataPermissionServiceImpl extends BaseServiceImpl<DataPermission> implements DataPermissionService {

    @Autowired
    private AdminUserRemoteService adminUserRemoteService;

    @Override
    public RtnInfo<PageInfoBT<DataPermissionVo>> list(DataPermissionDTO dataPermissionDTO){
        PageQuery<DataPermissionVo> pageQuery = new PageQuery<>(dataPermissionDTO.getOffset(), dataPermissionDTO.getLimit(), dataPermissionDTO);
        PageQuery<DataPermissionVo> result = this.sqlManager.pageQuery("dataPermission.selectPageList", DataPermissionVo.class, pageQuery);
        //为空直接返回
        if (CollectionUtils.isEmpty(result.getList())) {
            return RtnInfo.success(new PageInfoBT<>(result));
        }
        result.getList().forEach(item -> {
            UserSingleDetailQueryDTO userSingleDetailQueryDTO = new UserSingleDetailQueryDTO();
            userSingleDetailQueryDTO.setUserId(item.getCreateBy());
            item.setCreateName(adminUserRemoteService.singleDetailQuery(userSingleDetailQueryDTO).getData().getName());
            userSingleDetailQueryDTO.setUserId(item.getUpdateBy());
            item.setUpdateName(adminUserRemoteService.singleDetailQuery(userSingleDetailQueryDTO).getData().getName());
        });
        PageInfoBT<DataPermissionVo> re = new PageInfoBT<>(result);
        rebuild(re);
        return RtnInfo.success(re);
    }

    private void rebuild(PageInfoBT<DataPermissionVo> re){
        List<DataPermissionVo> list = re.getRows();
        if(CollectionUtils.isEmpty(list)){
            re.setTotal(0);
            return;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveInfo(DataPermission dataPermission){
        return this.save(dataPermission);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateInfo(DataPermission dataPermission){
        return this.updateById(dataPermission);
    }

    @Override
    public boolean addCheck(DataPermission dataPermission){
        LambdaQuery<DataPermission> query = sqlManager.lambdaQuery(DataPermission.class);
        DataPermission old = query.andEq(DataPermission::getRoleId,dataPermission.getRoleId())
                .andEq(DataPermission::getIsDelete, IsDeleteEnum.NOTDELETE.getCode()).single();
        return null == old;
    }

    @Override
    public boolean updateCheck(DataPermission dataPermission){
        LambdaQuery<DataPermission> query = sqlManager.lambdaQuery(DataPermission.class);
        List<DataPermission> orgList = query.andEq(DataPermission::getIsDelete,IsDeleteEnum.NOTDELETE.getCode())
                .andNotEq(DataPermission::getId,dataPermission.getId())
                .andEq(DataPermission::getRoleId,dataPermission.getRoleId()).select();
        return 0 >= orgList.size();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteInfo(Long id){
        DataPermission p = new DataPermission();
        p.setId(id);
        p.setIsDelete(IsDeleteEnum.DELETE.getCode());
        return this.updateById(p);
    }

    @Override
    public DataPermission getInfo(Long id){
        LambdaQuery<DataPermission> query = sqlManager.lambdaQuery(DataPermission.class);
        return query.andEq(DataPermission::getId,id).single();
    }

    @SneakyThrows
    @Override
    public <T> void getCurrentUserPermissionType(T entity){
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        String roleIds = adminUserVO.getRoleid();
        if (!StringUtil.isBlank(roleIds)){
            roleIds = roleIds.substring(0,roleIds.length()-1);
        }
        List<String> roleIdList = Arrays.asList(roleIds.split(","));
        List<Long> roleLongList = new ArrayList<>(roleIdList.size());
        roleIdList.forEach(item -> {
            roleLongList.add(Long.parseLong(item));
        });
        LambdaQuery<DataPermission> query = sqlManager.lambdaQuery(DataPermission.class);
        List<DataPermission> list = query.andIn(DataPermission::getRoleId, roleLongList)
                .andEq(DataPermission::getIsDelete,IsDeleteEnum.NOTDELETE.getCode())
                .orderBy("permission_type desc").select();
        if (0 < list.size()){
            Integer type = list.get(0).getPermissionType();
            if (type.equals(DataPermissionTypeEnum.ONLY_SELF.getCode())){
                Field createBy = entity.getClass().getDeclaredField("createBy");
                createBy.setAccessible(true);
                createBy.set(entity,adminUserVO.getId());
                createBy.setAccessible(false);
            }else if (type.equals(DataPermissionTypeEnum.ONLY_DEPT.getCode())){
                Field createBy = entity.getClass().getDeclaredField("deptId");
                createBy.setAccessible(true);
                createBy.set(entity,adminUserVO.getDeptid());
                createBy.setAccessible(false);
            }
        }
    }

    @SneakyThrows
    @Override
    public <T> void setPermissionData(T entity){
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        String roleIds = adminUserVO.getRoleid();
        if (!StringUtil.isBlank(roleIds)){
            roleIds = roleIds.substring(0,roleIds.length()-1);
        }
        List<String> roleIdList = Arrays.asList(roleIds.split(","));
        List<Long> roleLongList = new ArrayList<>(roleIdList.size());
        roleIdList.forEach(item -> {
            roleLongList.add(Long.parseLong(item));
        });
        LambdaQuery<DataPermission> query = sqlManager.lambdaQuery(DataPermission.class);
        List<DataPermission> list = query.andIn(DataPermission::getRoleId, roleLongList)
                .andEq(DataPermission::getIsDelete,IsDeleteEnum.NOTDELETE.getCode())
                .orderBy("permission_type desc").select();
        try{
            Field currentUser = entity.getClass().getDeclaredField("currentUser");
            currentUser.setAccessible(true);
            currentUser.set(entity,adminUserVO.getId());
            currentUser.setAccessible(false);
        }catch (Exception ignored) {}
        if (0 < list.size()){
            Integer type = list.get(0).getPermissionType();
            if (type.equals(DataPermissionTypeEnum.ONLY_SELF.getCode())){
                try{
                    Field permissionUser = entity.getClass().getDeclaredField("permissionUser");
                    permissionUser.setAccessible(true);
                    permissionUser.set(entity,adminUserVO.getId());
                    permissionUser.setAccessible(false);
                }catch (Exception ignored) {}
            }else if (type.equals(DataPermissionTypeEnum.ONLY_DEPT.getCode())){
                try{
                    Field permissionUser = entity.getClass().getDeclaredField("permissionUser");
                    permissionUser.setAccessible(true);
                    permissionUser.set(entity,adminUserVO.getId());
                    permissionUser.setAccessible(false);
                    Field permissionDept = entity.getClass().getDeclaredField("permissionDept");
                    permissionDept.setAccessible(true);
                    permissionDept.set(entity,adminUserVO.getDeptid());
                    permissionDept.setAccessible(false);
                }catch (Exception ignored) {}
            }
        }
    }


    @Override
    public List<DataPermission> getDataPermissionInfo(List<Long> roleLongList) {
        return sqlManager.lambdaQuery(DataPermission.class).andIn(DataPermission::getRoleId, roleLongList)
                .andEq(DataPermission::getIsDelete,IsDeleteEnum.NOTDELETE.getCode())
                .orderBy("permission_type desc").select();
    }

    @Override
    public Integer getDataPermissionLevel() {
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        String roleIds = adminUserVO.getRoleid();
        if (StringUtil.isEmpty(roleIds)){
            return DataPermissionTypeEnum.ONLY_SELF.getCode();
        }
        List<Long> roleLongList = Arrays.stream(roleIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
        List<DataPermission> list = this.getDataPermissionInfo(roleLongList);
        if (CollectionUtils.isEmpty(list)) {
            return DataPermissionTypeEnum.ONLY_SELF.getCode();
        }else {
            return list.get(0).getPermissionType();
        }
    }
}
